from os import PathLike
from typing import NamedTuple, Self, TypeAlias

import pygame

from vengine.ve_coord import Point2d

T_PathLike: TypeAlias = str | bytes | PathLike[str] | PathLike[bytes]

class VE_Color(NamedTuple):
    R: int
    G: int
    B: int
    A: int = 255
    
    def to_pygame(self) -> pygame.color.Color:
        return pygame.color.Color(self.R, self.G, self.B, self.A)

class VE_Font:
    def __init__(self, font: pygame.font.Font) -> None:
        self.font = font
    
    @classmethod
    def load(cls, path: T_PathLike, size: int) -> Self:
        return cls(
            pygame.font.Font(
                open(path),
                size
            )
        )
        
class VE_FontRender:
    def __init__(
        self,
        font: VE_Font,
        antialias: bool,
        color: VE_Color,
        background: VE_Color | None = None
    ) -> None:
        self.font = font
        self.antialias = antialias
        self.color = color
        self.background = background
        
        self.color_pygame = self.color.to_pygame()
        if self.background is None:
            self.background_pygame = None
        else:
            self.background_pygame = self.background.to_pygame()
        
    def render(self, text: str) -> pygame.Surface:
        return self.font.font.render(
            text,
            self.antialias,
            self.color_pygame,
            self.background_pygame
        )
        
class VE_Image:
    def __init__(self, image: pygame.Surface) -> None:
        self.image = image
    
    @classmethod
    def load(cls, path: T_PathLike, size: Point2d | None = None) -> Self:
        """Load an image

        Args:
            path (T_PathLike): image file path
            size (Point2d | None, optional): Scales image into size (width, height). 
            Defaults to None which uses original size.

        Returns:
            Self: A VE_Image object
        """
        surface = pygame.image.load(open(path))
        if size is None: return cls(surface)
        return cls(
            pygame.transform.scale(surface, (size.x, size.y))
        )
        
class VE_Sound:
    def __init__(self, sound: pygame.mixer.Sound) -> None:
        self.sound = sound
    
    @classmethod
    def load(cls, path: T_PathLike) -> Self:
        return cls(
            pygame.mixer.Sound(
                open(path)
            )
        )
